<template>
  <div class="antvx61" style="width； 100%; height: 100%;">
    <div id="container" style="width: 100%; height: 100%;"></div>
  </div>
</template>

<script>
import { Graph, Node, Point } from '@antv/x6'
import dagre from 'dagre'
export default {
  name: 'Antvx61',
  mounted () {
    Graph.registerNode(
      'org-node',
      {
        width: 180,
        height: 60,
        markup: [
          {
            tagName: 'rect',
            selector: 'body'
          },
          // {
          //   tagName: 'image',
          //   selector: 'avatar'
          // },
          {
            tagName: 'text',
            selector: 'rank'
          },
          // {
          //   tagName: 'text',
          //   selector: 'name'
          // }
        ],
        attrs: {
          body: {
            refWidth: '100%',
            refHeight: '100%',
            fill: '#fff',
            stroke: '#000',
            strokeWidth: 1,
            pointerEvents: 'visiblePainted'
          },
          avatar: {
            width: 48,
            height: 48,
            refX: 8,
            refY: 6
          },
          rank: {
            refX: '50%',
            refY: '50%',
            fill: '#000',
            fontFamily: 'Courier New',
            fontSize: 24,
            textAnchor: 'middle',
            textVerticalAnchor: 'middle',
            fontWeight: '700'
          },
          name: {
            refX: 0.9,
            refY: 0.6,
            fill: '#000',
            fontFamily: 'Courier New',
            fontSize: 14,
            fontWeight: '800',
            textAnchor: 'end'
          }
        }
      },
      true
    )
    Graph.registerNode(
      'org-node-circle',
      {
        width: 180,
        height: 60,
        markup: [
          {
            tagName: 'rect',
            selector: 'body'
          },
          {
            tagName: 'text',
            selector: 'rank'
          },
        ],
        attrs: {
          body: {
            refWidth: '100%',
            refHeight: '100%',
            fill: '#fff',
            stroke: '#000',
            strokeWidth: 1,
            rx: 80,
            ry: 80,
            pointerEvents: 'visiblePainted'
          },
          avatar: {
            width: 48,
            height: 48,
            refX: 8,
            refY: 6
          },
          rank: {
            refX: '50%',
            refY: '50%',
            fill: '#000',
            fontFamily: 'Courier New',
            fontSize: 24,
            textAnchor: 'middle',
            textVerticalAnchor: 'middle',
            fontWeight: '700'
          },
          name: {
            refX: 0.9,
            refY: 0.6,
            fill: '#000',
            fontFamily: 'Courier New',
            fontSize: 14,
            fontWeight: '800',
            textAnchor: 'end'
          }
        }
      },
      true
    )
    Graph.registerEdge(
      'org-edge',
      {
        zIndex: -1,
        attrs: {
          line: {
            fill: 'none',
            strokeLinejoin: 'round',
            strokeWidth: 2,
            stroke: '#A2B1C3',
            // sourceMarker: null,
            // targetMarker: null
          }
        }
      },
      true
    )
    const graph = new Graph({
      container: document.getElementById('container'),
      connecting: {
        anchor: 'top',
        router: {
          name: 'normal'
        }
      }
    })
    function member (x, y, rank, name, image, type) {
      return graph.addNode({
        x,
        y,
        shape: type == 'circle' ? 'org-node-circle' : 'org-node',
        attrs: {
          avatar: {
            opacity: 0.7,
            'xlink:href': image
          },
          rank: {
            text: rank,
            wordSpacing: '-5px',
            letterSpacing: 0
          },
          name: {
            text: name,
            fontSize: 13,
            fontFamily: 'Arial',
            letterSpacing: 0
          }
        }
      })
    }
    function link (source, target, vertices) {
      return graph.addEdge({
        vertices,
        source: {
          cell: source
        },
        target: {
          cell: target
        },
        shape: 'org-edge'
      })
    }
    // 自动布局
    function layout() {
      const nodes = graph.getNodes()
      const edges = graph.getEdges()
      const g = new dagre.graphlib.Graph()
      g.setGraph({ rankdir: dir, nodesep: 16, ranksep: 16 })
      g.setDefaultEdgeLabel(() => ({}))

      const width = 260
      const height = 90
      nodes.forEach((node) => {
        g.setNode(node.id, { width, height })
      })

      edges.forEach((edge) => {
        const source = edge.getSource()
        const target = edge.getTarget()
        g.setEdge(source.cell, target.cell)
      })

      dagre.layout(g)

      graph.freeze()

      g.nodes().forEach((id) => {
        const node = graph.getCell(id)
        if (node) {
          const pos = g.node(id)
          node.position(pos.x, pos.y)
        }
      })

      edges.forEach((edge) => {
        const source = edge.getSourceNode()
        const target = edge.getTargetNode()
        const sourceBBox = source.getBBox()
        const targetBBox = target.getBBox()

        console.log(sourceBBox, targetBBox)

        if ((dir === 'LR' || dir === 'RL') && sourceBBox.y !== targetBBox.y) {
          const gap = dir === 'LR' ? targetBBox.x - sourceBBox.x - sourceBBox.width : -sourceBBox.x + targetBBox.x + targetBBox.width
          const fix = dir === 'LR' ? sourceBBox.width : 0
          const x = sourceBBox.x + fix + gap / 2
          edge.setVertices([
            { x, y: sourceBBox.center.y },
            { x, y: targetBBox.center.y }
          ])
        } else if (
          (dir === 'TB' || dir === 'BT') && sourceBBox.x !== targetBBox.x
        ) {
          const gap = dir === 'TB' ? targetBBox.y - sourceBBox.y - sourceBBox.height : -sourceBBox.y + targetBBox.y + targetBBox.height
          const fix = dir === 'TB' ? sourceBBox.height : 0
          const y = sourceBBox.y + fix + gap / 2
          edge.setVertices([
            { x: sourceBBox.center.x, y },
            { x: targetBBox.center.x, y }
          ])
        } else {
          edge.setVertices([])
        }
      })

      graph.unfreeze()
    }
    // 布局方向
    const dir = 'TB' // LR RL TB BT
    const male = 'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*kUy8SrEDp6YAAAAAAAAAAAAAARQnAQ'
    const female = 'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*f6hhT75YjkIAAAAAAAAAAAAAARQnAQ'
    const bart = member(300, 70, '3', 'Bart Simpson', male, 'circle')
    const bart1 = member(300, 70, '1', 'Bart Simpson1', male, 'circle')
    const homer = member(90, 200, '6', 'Homer Simpson', male)
    const marge = member(300, 200, '4', 'Marge Simpson', female)
    const marge1 = member(300, 200, '2', 'Marge Simpson1', female)
    const maggie = member(400, 350, '5', 'Maggie Simpson', female)
    const lenny = member(190, 350, '7', 'Lenny Leonard', male)
    const carl = member(190, 500, '8', 'Carl Carlson', male)
    link(maggie, homer, [
      {
        x: 385,
        y: 180
      }
    ])
    link(homer, lenny, [
      {
        x: 385,
        y: 180
      }
    ])
    link(lenny, carl, [
      {
        x: 385,
        y: 180
      }
    ])
    link(bart1, marge1, [
      {
        x: 385,
        y: 180
      }
    ])
    link(marge1, maggie, [
      {
        x: 385,
        y: 180
      }
    ])
    link(bart, marge, [
      {
        x: 385,
        y: 180
      }
    ])
    link(marge, maggie, [
      {
        x: 385,
        y: 380
      }
    ])
    graph.zoomToFit({ padding: 20, maxScale: 1 })
    layout()
    graph.centerContent()
  }
}
</script>

<style lang="less" scoped>

</style>
